package lockDemo;

import java.util.concurrent.CountDownLatch;

/**
 * @author Ajie
 * @date 2019-10-11
 * @function 一针见血 ThreadLocal
 * http://threadlocal.cn
 * <p>
 * https://www.cnblogs.com/jasongj/p/8079718.html
 * <p>
 *
 * CountDownLaunch
 * -AQS-Park/unPark
 * 	* state就是构造方法初始化的数值N
 * 	    * await（）等待所有其他线程执行之后再执行，每次countDown计数器-1减一操作，直到计数器为0，
 * 	    然后调用unpark调用线程执行，通过await返回继续后续操作。
 * 	场景：
 * CountDownLatch 适用于一个线程去等待多个线程的情况。
 *
 */
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {

        int threads = 3;
        CountDownLatch countDownLatch = new CountDownLatch(threads);
        InnerClass innerClass = new InnerClass();
        for (int i = 1; i <= threads; i++) {
            new Thread(() -> {
                for (int j = 0; j < 4; j++) {
                    innerClass.add(String.valueOf(j));
                    innerClass.print();
                }
                innerClass.set("hello world");
                countDownLatch.countDown();
            }, "thread - " + i).start();
        }
        countDownLatch.await();
        System.out.println("over");
    }

    private static class InnerClass {

        public void add(String newStr) {
            StringBuilder str = threadLocal.get();
            threadLocal.set(str.append(newStr));
        }

        public void print() {
            System.out.printf("Thread name:%s , ThreadLocal hashcode:%s, Instance hashcode:%s, Value:%s\n",
                    Thread.currentThread().getName(),
                    threadLocal.hashCode(),
                    threadLocal.get().hashCode(),
                    threadLocal.get().toString());
        }

        public void set(String words) {
            threadLocal.set(new StringBuilder(words));
            System.out.printf("Set, Thread name:%s , ThreadLocal hashcode:%s,  Instance hashcode:%s, Value:%s\n",
                    Thread.currentThread().getName(),
                    threadLocal.hashCode(),
                    threadLocal.get().hashCode(),
                    threadLocal.get().toString());
        }
    }


    private static ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<StringBuilder>() {
        @Override
        protected StringBuilder initialValue() {
            return new StringBuilder();
        }
    };


}
